module ysyx_22040213_bubble(
	input [4:0] rs1,
	input [4:0] rs2,
	input [4:0] o_exe_rd,
	input [4:0] o_mem_rd,
	input [4:0] o_wb_rd,
	input exe_load,
//	input ID_to_EXE_valid,
	input ID_allow_in,
//	input EXE_allow_in,
	input EXE_ready_go,

	input [63:0] src1,
	input [63:0] src2,
	input [63:0] i_exe_adata,
	input [63:0] i_mem_wdata,
	input [63:0] i_wb_wdata,

	input AluData1_en,
	input AluData2_en,
	input [4:0] i_jump_en,
	input i_jumpr_en,
	input sm_en,
	input o_exe_w_en,
	input o_mem_w_en,
	input o_wb_w_en,
	input MEM_to_WB_valid,

	output [63:0] o_bub_src1,
	output [63:0] o_bub_src2,
	output ID_ready_go,
	output pc_stall,
	output exe_flush,
	output id_flush,
	output exe_bubble,
	output id_bubble

);
	/*verilator lint_off UNUSED*/
//	stall ? ID_src1 id_src2 hit o_exe_rd o_mem_rd o_wb_rd
	wire ID_valid = 1'b1;
	wire rd_src1_hit_exe = o_exe_w_en && (rs1 == o_exe_rd) && (rs1 != 0) && ID_valid;
	wire rd_src1_hit_mem = o_mem_w_en && (rs1 == o_mem_rd) && (rs1 != 0) && ID_valid;
	wire rd_src1_hit_wb = o_wb_w_en && (rs1 == o_wb_rd) && (rs1 != 0) && ID_valid;

	wire rd_src2_hit_exe = o_exe_w_en && (rs2 == o_exe_rd) && (rs2 != 0) && ID_valid;
	wire rd_src2_hit_mem = o_mem_w_en && (rs2 == o_mem_rd) && (rs2 != 0) && ID_valid;
	wire rd_src2_hit_wb = o_wb_w_en && (rs2 == o_wb_rd) && (rs2 != 0) && ID_valid;

	wire [2:0] src1_forward_en;
	wire [2:0] src2_forward_en;
	//AluData1_en || i_jump_en[0] for src1 were used
	assign src1_forward_en[2] = (AluData1_en || i_jumpr_en) && rd_src1_hit_exe;
	assign src1_forward_en[1] = (AluData1_en || i_jumpr_en) && rd_src1_hit_mem;
	assign src1_forward_en[0] = (AluData1_en || i_jumpr_en) && rd_src1_hit_wb;

	//AluData2_en || sm_en for src2 were used and sm_en for save instruction
	assign src2_forward_en[2] = (AluData2_en || sm_en ) && rd_src2_hit_exe;
	assign src2_forward_en[1] = (AluData2_en || sm_en ) && rd_src2_hit_mem;
	assign src2_forward_en[0] = (AluData2_en || sm_en ) && rd_src2_hit_wb;
/*
	MuxKey #(4, 4, 64) i0 (o_bub_src1, src1_forward_en, {
		4'b1xxx, i_exe_adata,
		4'b01xx, i_mem_wdata,
		4'b001x, i_wb_wdata,
		4'b0001, 64'b1 + src1
		});

	MuxKey #(4, 4, 64) i1 (o_bub_src2, src2_forward_en, {
		4'b1xxx, i_exe_adata,
		4'b01xx, i_mem_wdata,
		4'b001x, i_wb_wdata,
		4'b0001, src2		
		});
*/
	assign o_bub_src1 = src1_forward_en[2] ? i_exe_adata : src1_forward_en[1] ? i_mem_wdata : src1_forward_en[0] ? i_wb_wdata : src1;
	assign o_bub_src2 = src2_forward_en[2] ? i_exe_adata : src2_forward_en[1] ? i_mem_wdata : src2_forward_en[0] ? i_wb_wdata : src2;
	
	wire mem_forward_not_ok = (src1_forward_en[1] | src2_forward_en[1]) & ~MEM_to_WB_valid;

	// load and branch need stall   id_hit && exe_hit	
	wire id_hit_exe = (|src1_forward_en[2]) || (|src2_forward_en[2]);
	assign exe_bubble = id_hit_exe && exe_load ; //valid for the inst is vaild when compare
	assign exe_flush = exe_bubble && EXE_ready_go; //flush exe reg when mem receive valid data
	assign ID_ready_go = !exe_bubble & !mem_forward_not_ok;//!exe_bubble;// !exe_bubble;// && !id_bubble;// && !id_bubble;// exe_ready go  = 0

	//add a bubble when jump and wait til right address when harzard and
	//when id allow in
	assign id_bubble = | i_jump_en && (!exe_bubble) && ID_allow_in; 
	assign id_flush = id_bubble;

	// load to branch need to invalid inst; exe_bubble means load inst in exe;
	assign pc_stall = (| i_jump_en && (exe_bubble | (~MEM_to_WB_valid & rd_src1_hit_mem)));//indeed pcstall
endmodule
